#import "BWSelectionTool.h"
#import "BWSelectionLayer.h"
#import "BWLayer.h"
#import "BWLayerSet.h"
#import "BWGridGeometry.h"
#import "BWLayerView.h"
#import "BWCrossStitchChangeList.h"
#import "BWLayerSet.h"
#import "BWCrossStitchLayer.h"
#import "BWCrossStitchSet.h"

#import "BWColorKeyWindowController.h"


@implementation BWSelectionTool

- (id) initWithGeometry: (BWGridGeometry *) g
                 layers: (BWLayerSet *) l
              layerView: (BWLayerView *) lv
{
    if (self = [super initWithGeometry: g
                      layers: l
                      layerView: lv]) {

        // !!! UGH
        selectionLayer = (BWSelectionLayer *)[layers layerAtIndex: 0];
        [selectionLayer clearSelection];
    }

    return (self);

} // initWithGeometry

- (void) dealloc
{
    [selectionLayer clearSelection];
    [super dealloc];
} // dealloc


- (BOOL) handleMouseDown: (NSEvent *) event
                 atPoint: (NSPoint) mouse
{
    int row, column;
    [geometry getRow: &row
              andColumn: &column
              atPoint: mouse];

    startRow = endRow = row;
    startColumn = endColumn = column;
    
    [selectionLayer selectStartRow: startRow
           column: startColumn
           endRow: endRow
           column: endColumn];

    return (YES);

} // handleMouseDown


- (void) handleMouseDragged: (NSEvent *) event
                    atPoint: (NSPoint) mouse
{
    int row, column;
    [geometry getRow: &row
              andColumn: &column
              atPoint: mouse];

    endRow = row;
    endColumn = column;
    
    [selectionLayer selectStartRow: startRow
           column: startColumn
           endRow: endRow
           column: endColumn];

} // handleMouseDragged


- (void) handleMouseUp: (NSEvent *) event
               atPoint: (NSPoint) mouse
{

} // handleMouseUp


- (void) applyToSelectedCrossStitchLayers: (BWCrossStitchChangeList *) changes
{
    NSArray *affectedLayers = [self affectedLayers];
    NSEnumerator *enumerator = [affectedLayers objectEnumerator];

    BWLayer *layer;
    while (layer = [enumerator nextObject]) {

        if ([layer layerKind] == kLayerKind_CrossStitch) {
            BWCrossStitchLayer *cslayer = (BWCrossStitchLayer *) layer;
            
            if ([cslayer active]) {
                [cslayer setChangeList: changes];
                [cslayer applyChanges];
                [cslayer setChangeList: nil];
            }
        }
    }

} // applyToSelectedCrossStitchLayers


- (void) delete: (id) sender
{
    BWCrossStitchChangeList *changes;
    changes = [[BWCrossStitchChangeList alloc] init];

    int row, column;
    for (row = startRow; row <= endRow; row++) {
        for (column = startColumn; column <= endColumn; column++) {
            [changes markRemovedAtRow: row
                     column: column];
        }
    }

    [self applyToSelectedCrossStitchLayers: changes];

    [changes release];

} // delete


- (void) deleteThread: (BWThread *) thread
              inLayer: (BWCrossStitchLayer *) layer
{
    BWCrossStitchChangeList *changes;
    changes = [[BWCrossStitchChangeList alloc] init];

    BWCrossStitchSet *stitches = [layer crossStitches];

    int minRow, minColumn;
    int maxRow, maxColumn;
    minRow = MIN (startRow, endRow);
    maxRow = MAX (startRow, endRow);
    minColumn = MIN (startColumn, endColumn);
    maxColumn = MAX (startColumn, endColumn);

    int row, column;
    for (row = minRow; row <= maxRow; row++) {
        for (column = minColumn; column <= maxColumn; column++) {
            BWCrossStitch *stitch;
            
            if ([stitches getSymbol: &stitch  atRow: row
                          column: column]) {
                if ([stitch topThread] == thread) {
                    [changes markRemovedAtRow: row
                             column: column];
                }
            }
        }
    }

    [layer setChangeList: changes];
    [layer applyChanges];
    [layer setChangeList: nil];

    [changes release];

} // deleteThread


- (void) deleteColor: (id) sender
{
    BWThread *thread = [[BWColorKeyWindowController sharedController]
                           selectedThread];
    NSArray *affectedLayers = [self affectedLayers];
    NSEnumerator *enumerator = [affectedLayers objectEnumerator];

    BWLayer *layer;
    while (layer = [enumerator nextObject]) {
        BWLayerKind kind = [layer layerKind];

        if (kind == kLayerKind_CrossStitch) {
            [self deleteThread: thread
                  inLayer: (BWCrossStitchLayer *)layer];
        }
    }

} // deleteColor


- (void) selectAll: (id) sender
{
    startRow = startColumn = 0;
    endRow = [geometry countDown];
    endColumn = [geometry countAcross];

    [selectionLayer selectStartRow: startRow
           column: startColumn
           endRow: endRow
           column: endColumn];

} // selectAll


- (void) fill: (id) sender
{
    BWCrossStitchChangeList *changes;
    changes = [[BWCrossStitchChangeList alloc] init];

    BWThread *thread = [[BWColorKeyWindowController sharedController]
                           selectedThread];

    int row, column;
    for (row = startRow; row <= endRow; row++) {
        for (column = startColumn; column <= endColumn; column++) {
            [changes addStitchWithThread: thread
                     atRow: row
                     column: column];
        }
    }

    [self applyToSelectedCrossStitchLayers: changes];

    [changes release];

} // fill


- (BOOL) validateMenuItem: (id <NSMenuItem>) menuItem
{
    BOOL result = YES;

    if ([menuItem action] == @selector(delete:)
        || [menuItem action] == @selector(fill:)
        || [menuItem action] == @selector(deleteColor:)) {
        result = ![selectionLayer isEmptySelection];
    }

    return (result);

} // validateMenuItem


- (unsigned int) capabilities
{
    unsigned int capabilities = [super capabilities];
    
    capabilities |= kCapability_Selection;
    capabilities |= kCapability_AllLayers;

    return (capabilities);

} // capabilities


- (NSArray *) affectedLayers
{
    NSMutableArray *array = [NSMutableArray array];

    NSEnumerator *enumerator = [layers layerEnumerator];

    BWLayer *layer;
    while (layer = [enumerator nextObject]) {
        BWLayerKind kind = [layer layerKind];
        
        if (kind == kLayerKind_CrossStitch
            || kind == kLayerKind_BackStitch) {

            if ([layer active]) {
                [array addObject: layer];
            }
        }
    }

    return (array);

} // affectedLayers

- (NSString *) name
{
    return (@"Select a region of stitches");
} // name

@end // BWSelectionTool
